package com.youngjun.common.mybatis.service.support;

import com.youngjun.common.exception.CommonExceptionType;
import com.youngjun.common.mybatis.mapper.support.BaseMapper;
import com.youngjun.common.oss.expection.CommonException;
import com.youngjun.common.pojo.dto.support.BaseDTO;
import com.youngjun.common.pojo.vo.support.BaseVO;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Transactional
public interface BaseService<T, M extends BaseMapper<T>> {

    M getMapper();

    /**
     * 根据record的主键和isDeleted属性逻辑删除数据或恢复数据。
     *
     * @param record
     * @return
     */
    default int deleteWithLogic(Long record) {
        int result = getMapper().deleteWithLogic(record);
        if (result != 1) {
            throw new CommonException(CommonExceptionType.DB_DELETE_FAILED);
        }
        return result;
    }

    /**
     * 插入record的值
     *
     * @param record
     * @return
     */
    default int insert(T record) {
        int result = getMapper().insert(record);
        if (result != 1) {
            throw new CommonException(CommonExceptionType.DB_INSERT_FAILED);
        }
        return result;
    }

    /**
     * update by primary key， 已逻辑删除的无法更新
     *
     * @param record
     * @return
     */
    default int updateByPrimaryKey(T record) {
        int result = getMapper().updateByPrimaryKey(record);
        if (result != 1) {
            throw new CommonException(CommonExceptionType.DB_UPDATE_FAILED);
        }
        return result;
    }

    /**
     * 根据主键更新record不对空的属性，已逻辑删除的无法更新
     *
     * @param record
     * @return
     */
    default int updateWithOptionalByPrimaryKey(T record) {
        int result = getMapper().updateWithOptionalByPrimaryKey(record);
        if (result != 1) {
            throw new CommonException(CommonExceptionType.DB_UPDATE_FAILED);
        }
        return result;
    }

    /**
     * 根据record属性作为where条件查找，已逻辑删除的会排除
     *
     * @param record
     * @return
     */
    default T select(T record) {
        return getMapper().select(record);
    }


    /**
     * 查询所有，已逻辑删除的会排除
     *
     * @return
     */
    default List<T> selectAll() {
        return getMapper().selectAll();
    }

    /**
     * 根据record属性作为where条件批量查找，已逻辑删除的会排除
     *
     * @param record
     * @return
     */
    default List<T> selectAll(T record) {
        return getMapper().selectAll(record);
    }

    default <VO extends BaseVO> VO mapToVO(T record, Class<VO> voClass) {
        try {
            return mapToVO(record, voClass.newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    default <VO extends BaseVO> VO mapToVO(T record, VO vo) {
        vo.getVOMapper().map(record, vo);
        return vo;
    }

    /**
     * 根据record属性作为where条件查找，已逻辑删除的会排除，返回VO对象
     *
     * @param record
     * @return
     */
    default <VO extends BaseVO> VO selectVO(T record, VO vo) {
        T result = select(record);
        if (result != null) {
            return mapToVO(result, vo);
        }
        return null;
    }

    /**
     * 根据record属性作为where条件查找，已逻辑删除的会排除，返回VO对象
     *
     * @param record
     * @return
     */
    default <VO extends BaseVO> VO selectVO(T record, Class<? extends VO> voClass) {
        T result = select(record);
        if (result != null) {
            return mapToVO(result, voClass);
        }
        return null;
    }

    /**
     * 查询所有，已逻辑删除的会排除，返回VO对象
     *
     * @return
     */
    default <VO extends BaseVO> List<VO> selectAllVO(Class<VO> voClass) {
        return getMapper()
                .selectAll()
                .stream()
                .map(item -> mapToVO(item, voClass))
                .collect(Collectors.toList());
    }

    /**
     * 根据record属性作为where条件批量查找，已逻辑删除的会排除，返回VO对象
     *
     * @param record
     * @return
     */
    default <VO extends BaseVO> List<VO> selectAllVO(T record, Class<VO> voClass) {
        return getMapper()
                .selectAll(record)
                .stream()
                .map(item -> mapToVO(item, voClass))
                .collect(Collectors.toList());
    }

    default <DTO extends BaseDTO> DTO mapToDTO(T record, Class<DTO> dtoClass) {
        try {
            return mapToDTO(record, dtoClass.newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    default <DTO extends BaseDTO> DTO mapToDTO(T record, DTO dto) {
        dto.getDTOMapper().map(record, dto);
        return dto;
    }

    /**
     * @param record
     * @return
     */
    default <DTO extends BaseDTO> DTO selectDTO(T record, DTO dto) {
        T result = select(record);
        if (result != null) {
            return mapToDTO(result, dto);
        }
        return null;
    }

    /**
     * @param record
     * @return
     */
    default <DTO extends BaseDTO> DTO selectDTO(T record, Class<? extends DTO> dtoClass) {
        T result = select(record);
        if (result != null) {
            return mapToDTO(result, dtoClass);
        }
        return null;
    }

    /**
     * @param record
     * @param dtoClass
     * @param <DTO>
     * @return
     */
    default <DTO extends BaseDTO> List<DTO> selectAllDTO(T record, Class<DTO> dtoClass) {
        return getMapper()
                .selectAll(record)
                .stream()
                .map(item -> mapToDTO(item, dtoClass))
                .collect(Collectors.toList());

    }
}
